package com.woniuxy.gateway.filter;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.woniuxy.commons.enums.ResultEnum;
import com.woniuxy.commons.enums.TokenEnum;
import com.woniuxy.commons.util.JwtUtil;
import com.woniuxy.commons.util.ResponseResult;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
import reactor.netty.http.server.HttpServerResponse;

import javax.annotation.Resource;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.List;

/**
 * @Author: yangtao
 * @date 2021/8/4 15:39
 * @Version 1.0
 */
@Component   //加入IOC容器
public class CustomFilter implements GlobalFilter, Ordered {
    @Resource
    private RedisTemplate<String,Object> redisTemplate;
    //执行过滤的方法，作用与zuul中的run方法一样
    //参数1：网络服务交换机
    //参数二:过滤器链
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        //获取到request
        ServerHttpRequest request = exchange.getRequest();
        //2、获取请求头(token)
        List<String> tokens = request.getHeaders().get("authorization");
        List<String> refreshTokens = request.getHeaders().get("refreshToken");
        String token=null;
        String refreshToken=null;
        if(tokens!=null&&tokens.size()!=0){
            token=tokens.get(0);
        }
        if(refreshTokens!=null&&refreshTokens.size()!=0){
            refreshToken=refreshTokens.get(0);
        }

        //3、获取uri
        String uri = request.getURI().getPath();
        System.out.println(uri);

        //判断是否需要登录才能进行操作
        if (!requireAuth(uri)){
            return chain.filter(exchange);  //放行，将exchangge交给下一个过滤器执行过滤
        }

        //执行到此处说明需要认证
        if (refreshToken==null||token==null){
            //没有登录,中断请求
            DataBuffer dataBuffer = result(exchange);
            return exchange.getResponse().writeWith(Mono.just(dataBuffer));
        }
        //执行到此处说明都有，合法性未知
        //5、判断refreshtoken是否合法  判断redis中是否有refreshtoken这个key，如果有则合法
        if (redisTemplate.hasKey(refreshToken)){
            // 合法
            System.out.println("合法————————————————————————————————————————————————");
        }else {
            System.out.println("不合法————————————————————————————————————————————————");
            DataBuffer dataBuffer = result(exchange);
            return exchange.getResponse().writeWith(Mono.just(dataBuffer));
        }

        //6、判断token是否合法
        if (JwtUtil.verify(token)== TokenEnum.TOKEN_BAD){
            DataBuffer dataBuffer = result(exchange);
            return exchange.getResponse().writeWith(Mono.just(dataBuffer));
            //伪造不合法  请求中断
        }else if (JwtUtil.verify(token)== TokenEnum.TOKEN_EXPIRE){
            //过期，生成新的token返回前段 请求不中断
            //从token中获取账号
            String account = JwtUtil.getUname(token);
            token=JwtUtil.generateToken(account);
            //返回给浏览器
            exchange.getResponse().getHeaders().add("authorization",token);
            exchange.getResponse().getHeaders().add("Access-Control-Expose-Headers","authorization,refreshToken");
            //通过refreshtoken修改redis中的token

        }
        //执行到此处说明合法，放行

        //假设访问goods开头的需要登录，当前没有登陆，就应该返回json告知应该登陆，当前请求应该终止

        return chain.filter(exchange);  //放行，将exchangge交给下一个过滤器执行过滤
    }


    //指定执行顺序：值越小，越先执行，可以是负数
    @Override
    public int getOrder() {
        return 0;
    }

    //返回一个布尔值，是否需要登录
    public boolean requireAuth(String uri){
        List<String> uris = Arrays.asList(
                "/auth/login",
                "/auth/regist",
                "/file/upload"
        );
        for (String s : uris) {
              if(uri.startsWith(s)){
                  return false;
              }
        }
        return true;
    }

    //返回结果的方法
    private DataBuffer result(ServerWebExchange exchange){
        //获取response
        ServerHttpResponse response = exchange.getResponse();
        ResponseResult<Object> result = new ResponseResult<>(500, ResultEnum.NO_LOGIN, "请你登录", null);

        try {
            //转为json
            String json = new ObjectMapper().writeValueAsString(result);
            //转bytes数组
            byte[] bytes = json.getBytes(StandardCharsets.UTF_8); //指定字符编码
            //将bytes类型的数据存放到缓冲区
            DataBuffer dataBuffer = response.bufferFactory().wrap(bytes);
            //设置响应头
            response.getHeaders().add("Content-Type","application/json;charset=utf-8");
            //返回数据,并结束请求
            return dataBuffer;
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
        return null;
    }
}
